package com.duolebo.uteped_sdk.utils;


import android.Manifest;
import android.text.TextUtils;
import android.util.Log;

import com.duolebo.uteped_sdk.UTEPedBleClientHelper;
import com.duolebo.uteped_sdk.db.UTEPedDb;
import com.google.gson.Gson;
import com.jieli.jl_bt_ota.util.BluetoothUtil;
import com.jieli.jl_bt_ota.util.CHexConver;
import com.yc.nadalsdk.bean.JLOtaStateInfo;
import com.yc.nadalsdk.bean.Response;
import com.yc.nadalsdk.ble.open.DeviceModeJX;
import com.yc.nadalsdk.ble.open.UteBleClient;
import com.yc.nadalsdk.listener.BleConnectStateListener;
import com.yc.nadalsdk.log.LogUtils;
import com.yc.nadalsdk.scan.UteScanDevice;

import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

/**
 * @Author: LiuYang
 * @Date: 2023/12/27 13:07
 * @Description: 鉴于sdk各种状态无法读取，或者是混乱，这里用一个设备类来保存每个所连接手表相关需要存储的数据
 *  并且进行一些月手表设备相关的解绑销毁工作
 */
public class DeviceHelper implements BleConnectStateListener {

    private final static String TAG = "DeviceHelper";
    private final static long CONN_CHECK_TIME = 40 * 1000L;
    private final static long STATE_CHECK_TIME = 20 * 1000L;

    private static DeviceHelper instance;
    public static DeviceHelper getInstance() {
        if (instance == null) {
            instance = new DeviceHelper();
        }

        return instance;
    }

    private boolean isRemoving = false;

    private SPHelper deviceSpHelper;// 存储与绑定设备相关数据
    private String address = "";
    private int status = BleConnectStateListener.STATE_DISCONNECTED;
    private final UteBleClient uteBleClient;

    private boolean isUpgrading = false;
    private long upgradingCompleteTime = 0L;
    private Timer connCheckTimer;

    private final List<UteScanDevice> scanDevices = new ArrayList<>();

    public DeviceHelper() {
        String address = SPHelper.shareInstance().getString(Const.KEY_ADDRESS, "");
        if (!TextUtils.isEmpty(address)) {
            initPref(address);
        }

        uteBleClient = UteBleClient.getUteBleClient();
        UTEPedBleClientHelper.shareInstance().addBleConnectStateListener(this);
    }
    /**
     * initPref
     * @param address 以address区分不同设备的信息存储
     */
    public void initPref(String address) {
        this.address = address;
        deviceSpHelper = SPHelper.getDefaultInstance(Tools.getApplicationContext(), address);
        SPHelper.shareInstance().putAndCommit(Const.KEY_ADDRESS, address);

        startCheckTimer();
    }

    public void connect(String address) {
        String connectAddress = address;
        boolean isOnOTA = false;
        if (isJieLi()) {
            boolean isUpgrading = DeviceHelper.getInstance().isUpgrading();
            if (isUpgrading && SPHelper.shareInstance().getBoolean(Const.JL_OTA_STAGE, false)) {
                connectAddress = deviceAddressUp1(address);
                isOnOTA = true;
                Log.d(TAG, "杰理OTA 中，地址+1");
            }
            else if(isOnOTA(address)){
                SPHelper.shareInstance().putAndCommit(Const.JL_OTA_STAGE, true);
                isOnOTA = true;
            }
        }
        if (isOnOTA) {
            uteBleClient.setSupportUserIdPair(false);
        }

        doConnect(connectAddress);
    }

    private boolean isOnOTA(String address) {
        for (UteScanDevice device:scanDevices) {
            if (address.equals(device.getDevice().getAddress()) && isJLOtaSecondStage(device)) {
                return true;
            }
        }

        return false;
    }

    public void setScanDevices(List<UteScanDevice> scanDevices) {
        this.scanDevices.clear();
        this.scanDevices.addAll(scanDevices);
    }

    public void startCheckTimer() {
        Log.d(TAG, "start check timer...");
        cancelCheckTimer();
        connCheckTimer = new Timer();
        connCheckTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                autoConnectDevice();
            }
        }, CONN_CHECK_TIME, CONN_CHECK_TIME);
    }

    public void cancelCheckTimer() {
        if (connCheckTimer != null) {
            Log.d(TAG, "cancel check timer");
            connCheckTimer.cancel();
            connCheckTimer = null;
        }
        else {
            Log.d(TAG, "check timer already canceled.");
        }
    }

    private void doConnect(String address) {
        Log.d(TAG, "connect device :" + address);
        if (uteBleClient == null) {
            Log.d(TAG, "uteBleClient is null");
            return;
        }
        if (!uteBleClient.isBluetoothEnable()) {
            Log.d(TAG, "bluetooth is not enabled");
            return;
        }
        if (uteBleClient.isConnected()) {
            Log.d(TAG, "device already connected");
            return;
        }
        if (this.status == BleConnectStateListener.STATE_CONNECTING) {
            Log.d(TAG, "device is connecting");
            return;
        }
        if (TextUtils.isEmpty(address)) {
            Log.d(TAG, "address is empty");
            return;
        }

        try {
            uteBleClient.connect(address);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void autoConnectDevice() {
        Log.d(TAG, "auto connect device");
        doConnect(this.address);
    }

    public void onDeviceDisconnect(String address) {
        removeUnbindDeviceData(address);
        if (deviceSpHelper != null) {
            deviceSpHelper.removeAll();
        }
        SPHelper.shareInstance().remove(Const.KEY_ADDRESS);
        SPHelper.shareInstance().remove(Const.JL_OTA_STAGE);
        this.address = "";
    }

    public void save(String key, boolean value) {
        if (deviceSpHelper == null)
            return;
        deviceSpHelper.putAndCommit(key, value);
    }

    public boolean read(String key, boolean defaultValue) {
        if (deviceSpHelper == null)
            return defaultValue;
        return deviceSpHelper.getBoolean(key, defaultValue);
    }

    private void removeUnbindDeviceData(String address) {
        if (isRemoving)
            return;

        isRemoving = true;

        new Thread(() -> {
            UTEPedDb.shareInstance().removeData(address);
            isRemoving = false;
        }).start();
    }

    @Override
    public void onConnecteStateChange(int status) {
        if (connCheckTimer != null) {
            this.status = status;
            // 这里增加一个超时重置，放置手表连接过程中断开的情况
            if (BleConnectStateListener.STATE_CONNECTING == status) {
                startStateCheckTimer();
            }
        }

        if (BleConnectStateListener.STATE_CONNECTED == status) {
            if (isJieLi()) {
                Response<?> response =  UteBleClient.getUteBleClient().getUteBleConnection().queryJlOtaStatus();
                if (response.isSuccess()) {
                    JLOtaStateInfo info = (JLOtaStateInfo) response.getData();
                    Log.d(TAG, "JLOtaStateInfo = " + new Gson().toJson(info));
                }
            }
        }
    }

    public void setUpgrading(boolean isUpgrading) {
        this.isUpgrading = isUpgrading;
        if (!isUpgrading) {
            this.upgradingCompleteTime = System.currentTimeMillis();
        }
    }

    public boolean isUpgrading() {
        return isUpgrading;
    }

    /**
     * 手表在升级完成之后，系统会解绑蓝牙配对，这时候断开连类型传递给flutter端变成DISCONNECT_TYPE_BOND
     *
     * @return 是不是刚刚进行了OTA
     */
    public boolean isUpgradingCompleteSoon() {
        return System.currentTimeMillis() - this.upgradingCompleteTime < 3 * 1000L;
    }

    Timer stateCheckTimer;
    public void startStateCheckTimer() {
        Log.d(TAG, "start state check timer...");
        cancelStateCheckTimer();
        stateCheckTimer = new Timer();
        stateCheckTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                if (BleConnectStateListener.STATE_CONNECTING == status) {
                    status = BleConnectStateListener.STATE_DISCONNECTED;
                }
            }
        }, STATE_CHECK_TIME);
    }

    public void cancelStateCheckTimer() {
        if (stateCheckTimer != null) {
            Log.d(TAG, "cancel state check timer");
            stateCheckTimer.cancel();
            stateCheckTimer = null;
        }
        else {
            Log.d(TAG, "state check timer already canceled.");
        }
    }

    public void release() {
        UTEPedBleClientHelper.shareInstance().removeBleConnectStateListener(this);
        cancelCheckTimer();
        cancelStateCheckTimer();
    }

    private String deviceAddressUp1(String address) {
        byte[] data = BluetoothUtil.addressCovertToByteArray(address);
        int value = CHexConver.byteToInt(data[data.length - 1]) + 1;
        data[data.length - 1] = CHexConver.intToByte(value);
        String newAddress = BluetoothUtil.hexDataCovetToAddress(data);
        Log.d(TAG, "deviceAddressUp1 address = "+address+",newAddress = "+newAddress);
        return newAddress;
    }

    private boolean isJLOtaSecondStage(UteScanDevice device) {
        byte[] scanRecord = device.getScanRecord();
        StringBuilder stringBuilder = new StringBuilder(scanRecord.length);
        for (byte byteChar : scanRecord) {
            stringBuilder.append(String.format("%02X ", byteChar));
        }

        return stringBuilder.toString().contains("55 55 34 12");
    }

    public boolean isJieLi() {
        return DeviceModeJX.isHasFunction_7(DeviceModeJX.IS_PLATFORM_JLAC701);
    }

    public boolean isJuXin() {
        return DeviceModeJX.isHasFunction_7(DeviceModeJX.IS_PLATFORM_JXATS3085L);
    }
}
